/*
 * @Author: 0x9DEFA478
 * @Date: 2021-12-17 21:40:46
 * @LastEditTime: 2022-01-07 21:23:55
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "IP_SPI.h"


//状态机刷新
static void IP_SPI_MasterFullDuplex_byte_TransStatusRefresh(void* v);
//状态机刷新
static void IP_SPI_MasterFullDuplex_uint16_TransStatusRefresh(void* v);
//DMA中断调用
static void IP_SPI_MasterFullDuplex_DMA_IRQ(void* v);
//状态机刷新
static void IP_SPI_MasterOnlyTx_byte_TransStatusRefresh(void* v);
//状态机刷新
static void IP_SPI_MasterOnlyTx_uint16_TransStatusRefresh(void* v);
//DMA中断调用
static void IP_SPI_MasterOnlyTx_DMA_IRQ(void* v);




int IP_SPI_MasterFullDuplex_IsBusy(void* v){
  IP_SPI* ip_spi;

  ip_spi=v;

  if((cIP_SPI_rxDMA(ip_spi)->CR&DMA_SxCR_EN)!=0U){
    //RxDMA正在传输
    return -1;
  }
  
  return 0;
}

int IP_SPI_MasterOnlyTx_IsBusy(void* v){
  IP_SPI* ip_spi;

  ip_spi=v;

  if((cIP_SPI_txDMA(ip_spi)->CR&DMA_SxCR_EN)!=0U){
    //TxDMA正在传输
    return -1;
  }
  if((cIP_SPI_SPI(ip_spi)->SR&SPI_SR_TXC)==0U){
    return -1;
  }

  return 0;
}





/**
 * @brief SPI是否忙碌
 * @param ip_spi IP_SPI对象
 * @return 0:空闲 SPI可以开始一段新的传输 其他:SPI忙碌
 */
int IP_SPI_Master_IsBusy(IP_SPI* ip_spi){
  if(ip_spi->Mode.Master.Busy!=0){
    return -1;
  }
  return ip_spi->Mode.Master.IsBusy(ip_spi);
}

/**
 * @brief 设置位宽 该方法不会检查BitWidth的合理性
 * 在SPI空闲时才能调用
 * @param ip_spi IP_SPI对象
 * @param BitWidth 位宽
 * @return 无
 */
void IP_SPI_Master_SetBitWidth(IP_SPI* ip_spi,unsigned int BitWidth){
  unsigned int CR1;
  unsigned int CFG1;
  unsigned int DMA_CR;

  if(ip_spi->BitWidth==BitWidth){
    //无需修改
    return;
  }
  ip_spi->BitWidth=BitWidth;

  CFG1=BitWidth-1U;
  CFG1=(CFG1<<SPI_CFG1_DSIZE_Pos)&SPI_CFG1_DSIZE_Msk;


  CR1=cIP_SPI_SPI(ip_spi)->CR1;

  //失能SPI
  CR1&=(~SPI_CR1_SPE);
  cIP_SPI_SPI(ip_spi)->CR1=CR1;

  //设置位宽
  cIP_SPI_SPI(ip_spi)->CFG1=(cIP_SPI_SPI(ip_spi)->CFG1&(~SPI_CFG1_DSIZE_Msk))|CFG1;
  //设置DMA位宽
  if(BitWidth>16U){
    DMA_CR=(2U<<DMA_SxCR_MSIZE_Pos)|(2U<<DMA_SxCR_PSIZE_Pos);
  }else if(BitWidth>8U){
    DMA_CR=(1U<<DMA_SxCR_MSIZE_Pos)|(1U<<DMA_SxCR_PSIZE_Pos);
  }else{
    DMA_CR=(0U<<DMA_SxCR_MSIZE_Pos)|(0U<<DMA_SxCR_PSIZE_Pos);
  }
  if(ip_spi->Instance.DMA_Tx!=NULL){
    cIP_SPI_txDMA(ip_spi)->CR=(cIP_SPI_txDMA(ip_spi)->CR&(~(DMA_SxCR_MSIZE_Msk|DMA_SxCR_PSIZE_Msk)))|DMA_CR;
  }
  if(ip_spi->Instance.DMA_Rx!=NULL){
    cIP_SPI_rxDMA(ip_spi)->CR=(cIP_SPI_rxDMA(ip_spi)->CR&(~(DMA_SxCR_MSIZE_Msk|DMA_SxCR_PSIZE_Msk)))|DMA_CR;
  }

  //使能SPI
  CR1|=SPI_CR1_SPE;
  cIP_SPI_SPI(ip_spi)->CR1=CR1;

  //启动传输
  CR1|=SPI_CR1_CSTART;
  cIP_SPI_SPI(ip_spi)->CR1=CR1;
 
}

/**
 * @brief 设置中断模式下的传输完成回调
 * 在SPI空闲时才能调用
 * @param ip_spi IP_SPI对象
 * @param Callback 回调函数 在仅发送模式下 此回调被调用时可能SPI仍在传输(虽然DMA已经传输完毕 但还可能有一些数据在spi发送缓存中没有发送完毕) 需调用IP_SPI_Master_IsBusy()来确定真正的状态
 * @param Callback_v 回调函数传入的参数
 * @return 无
 */
void IP_SPI_Master_SetCommunicationDoneCallback(IP_SPI* ip_spi,void (*Callback)(void*),void* Callback_v){
  
  ip_spi->Mode.Master.Callback_v=Callback_v;
  ip_spi->Mode.Master.CommunicationDoneCallback=Callback;
}








/**
 * @brief SPI发送接收多字节 不阻塞线程 SPI进入忙碌状态直到发送结束
 * 在SPI空闲时才能调用 使用时应注意SPI当前的位宽
 * 使用之前确保已通过调用 IP_SPI_Master_SetCommunicationDoneCallback() 来设置传输完成回调
 * @param ip_spi IP_SPI对象
 * @param TxData 发送数组的头指针
 * @param RxData 接收数组的头指针
 * @param Length 发送数量 单位:字节 长度不限
 * @return 无
 */
void IP_SPI_MasterFullDuplex_byteCommunication(IP_SPI* ip_spi,void* TxData,void* RxData,int Length){

  if(Length<=0){
    return;
  }

  ip_spi->Mode.Master.Busy=-1;
  ip_spi->Mode.Master.RemainingSize=Length;
  ip_spi->Mode.Master.Tx_Buffer=TxData;
  ip_spi->Mode.Master.Rx_Buffer=RxData;

  ip_spi->Mode.Master.TransStatusRefresh=IP_SPI_MasterFullDuplex_byte_TransStatusRefresh;
  ip_spi->Instance.DMA_Rx->SetIrqCallback(IP_SPI_MasterFullDuplex_DMA_IRQ,ip_spi);
  cIP_SPI_rxDMA(ip_spi)->CR|=DMA_SxCR_TCIE;//使能完成中断

  ip_spi->Mode.Master.TransStatusRefresh(ip_spi);
}

/**
 * @brief SPI发送接收多半字 不阻塞线程 SPI进入忙碌状态直到发送结束
 * 在SPI空闲时才能调用 使用时应注意SPI当前的位宽
 * 使用之前确保已通过调用 IP_SPI_Master_SetCommunicationDoneCallback() 来设置传输完成回调
 * @param ip_spi IP_SPI对象
 * @param TxData 发送数组的头指针
 * @param RxData 接收数组的头指针
 * @param Length 发送数量 单位:字节 长度不限
 * @return 无
 */
void IP_SPI_MasterFullDuplex_uint16Communication(IP_SPI* ip_spi,void* TxData,void* RxData,int Length){

  if(Length<=0){
    return;
  }

  ip_spi->Mode.Master.Busy=-1;
  ip_spi->Mode.Master.RemainingSize=Length;
  ip_spi->Mode.Master.Tx_Buffer=TxData;
  ip_spi->Mode.Master.Rx_Buffer=RxData;

  ip_spi->Mode.Master.TransStatusRefresh=IP_SPI_MasterFullDuplex_uint16_TransStatusRefresh;
  ip_spi->Instance.DMA_Rx->SetIrqCallback(IP_SPI_MasterFullDuplex_DMA_IRQ,ip_spi);
  cIP_SPI_rxDMA(ip_spi)->CR|=DMA_SxCR_TCIE;//使能完成中断

  ip_spi->Mode.Master.TransStatusRefresh(ip_spi);
}




/**
 * @brief SPI发送多字节 不阻塞线程 SPI进入忙碌状态直到发送结束
 * 在SPI空闲时才能调用 使用时应注意SPI当前的位宽
 * 使用之前确保已通过调用 IP_SPI_Master_SetCommunicationDoneCallback() 来设置传输完成回调
 * @param ip_spi IP_SPI对象
 * @param TxData 发送数组的头指针
 * @param Length 发送数量 单位:字节 长度不限
 * @return 无
 */
void IP_SPI_MasterOnlyTx_byteCommunication(IP_SPI* ip_spi,void* TxData,int Length){

  if(Length<=0){
    return;
  }

  ip_spi->Mode.Master.Busy=-1;
  ip_spi->Mode.Master.RemainingSize=Length;
  ip_spi->Mode.Master.Tx_Buffer=TxData;
  ip_spi->Mode.Master.Rx_Buffer=(void*)0;

  ip_spi->Mode.Master.TransStatusRefresh=IP_SPI_MasterOnlyTx_byte_TransStatusRefresh;
  ip_spi->Instance.DMA_Tx->SetIrqCallback(IP_SPI_MasterOnlyTx_DMA_IRQ,ip_spi);
  cIP_SPI_txDMA(ip_spi)->CR|=DMA_SxCR_TCIE;//使能完成中断

  ip_spi->Mode.Master.TransStatusRefresh(ip_spi);
}

/**
 * @brief SPI发送多半字 不阻塞线程 SPI进入忙碌状态直到发送结束
 * 在SPI空闲时才能调用 使用时应注意SPI当前的位宽
 * 使用之前确保已通过调用 IP_SPI_Master_SetCommunicationDoneCallback() 来设置传输完成回调
 * @param ip_spi IP_SPI对象
 * @param TxData 发送数组的头指针
 * @param Length 发送数量 单位:字节 长度不限
 * @return 无
 */
void IP_SPI_MasterOnlyTx_uint16Communication(IP_SPI* ip_spi,void* TxData,int Length){

  if(Length<=0){
    return;
  }

  ip_spi->Mode.Master.Busy=-1;
  ip_spi->Mode.Master.RemainingSize=Length;
  ip_spi->Mode.Master.Tx_Buffer=TxData;
  ip_spi->Mode.Master.Rx_Buffer=(void*)0;

  ip_spi->Mode.Master.TransStatusRefresh=IP_SPI_MasterOnlyTx_uint16_TransStatusRefresh;
  ip_spi->Instance.DMA_Tx->SetIrqCallback(IP_SPI_MasterOnlyTx_DMA_IRQ,ip_spi);
  cIP_SPI_txDMA(ip_spi)->CR|=DMA_SxCR_TCIE;//使能完成中断

  ip_spi->Mode.Master.TransStatusRefresh(ip_spi);
}








//状态机刷新
static void IP_SPI_MasterFullDuplex_byte_TransStatusRefresh(void* v){
  IP_SPI* ip_spi;
  int RemainingSize;
  unsigned char* Tx_Buffer;
  unsigned char* Rx_Buffer;

  ip_spi=v;
  
  RemainingSize=ip_spi->Mode.Master.RemainingSize;
  if(RemainingSize==0){
    //传输完成

    cIP_SPI_rxDMA(ip_spi)->CR&=(~DMA_SxCR_TCIE);//失能完成中断
    ip_spi->Mode.Master.Busy=0;//解除忙碌状态
    ip_spi->Mode.Master.CommunicationDoneCallback(ip_spi->Mode.Master.Callback_v);

  }else{
    //传输未完成

    Tx_Buffer=ip_spi->Mode.Master.Tx_Buffer;
    Rx_Buffer=ip_spi->Mode.Master.Rx_Buffer;

    if(RemainingSize>65535){
      cIP_SPI_txDMA(ip_spi)->NDTR=65535U;
      cIP_SPI_txDMA(ip_spi)->M0AR=(unsigned int)Tx_Buffer;
      cIP_SPI_rxDMA(ip_spi)->NDTR=65535U;
      cIP_SPI_rxDMA(ip_spi)->M0AR=(unsigned int)Rx_Buffer;

      ip_spi->Mode.Master.RemainingSize=RemainingSize-65535;
      ip_spi->Mode.Master.Tx_Buffer=&Tx_Buffer[65535];
      ip_spi->Mode.Master.Rx_Buffer=&Rx_Buffer[65535];
    }else{
      cIP_SPI_txDMA(ip_spi)->NDTR=(unsigned int)RemainingSize;
      cIP_SPI_txDMA(ip_spi)->M0AR=(unsigned int)Tx_Buffer;
      cIP_SPI_rxDMA(ip_spi)->NDTR=(unsigned int)RemainingSize;
      cIP_SPI_rxDMA(ip_spi)->M0AR=(unsigned int)Rx_Buffer;

      ip_spi->Mode.Master.RemainingSize=0;
    }

    oIP_DMA_ClearAllBit_IFCR(ip_spi->Instance.DMA_Tx);
    oIP_DMA_ClearAllBit_IFCR(ip_spi->Instance.DMA_Rx);

    cIP_SPI_rxDMA(ip_spi)->CR|=DMA_SxCR_EN;//使能DMA
    cIP_SPI_txDMA(ip_spi)->CR|=DMA_SxCR_EN;//使能DMA
  }
}

//状态机刷新
static void IP_SPI_MasterFullDuplex_uint16_TransStatusRefresh(void* v){
  IP_SPI* ip_spi;
  int RemainingSize;
  unsigned short* Tx_Buffer;
  unsigned short* Rx_Buffer;

  ip_spi=v;
  
  RemainingSize=ip_spi->Mode.Master.RemainingSize;
  if(RemainingSize==0){
    //传输完成

    cIP_SPI_rxDMA(ip_spi)->CR&=(~DMA_SxCR_TCIE);//失能完成中断
    ip_spi->Mode.Master.Busy=0;//解除忙碌状态
    ip_spi->Mode.Master.CommunicationDoneCallback(ip_spi->Mode.Master.Callback_v);

  }else{
    //传输未完成

    Tx_Buffer=ip_spi->Mode.Master.Tx_Buffer;
    Rx_Buffer=ip_spi->Mode.Master.Rx_Buffer;

    if(RemainingSize>65535){
      cIP_SPI_txDMA(ip_spi)->NDTR=65535U;
      cIP_SPI_txDMA(ip_spi)->M0AR=(unsigned int)Tx_Buffer;
      cIP_SPI_rxDMA(ip_spi)->NDTR=65535U;
      cIP_SPI_rxDMA(ip_spi)->M0AR=(unsigned int)Rx_Buffer;

      ip_spi->Mode.Master.RemainingSize=RemainingSize-65535;
      ip_spi->Mode.Master.Tx_Buffer=&Tx_Buffer[65535];
      ip_spi->Mode.Master.Rx_Buffer=&Rx_Buffer[65535];
    }else{
      cIP_SPI_txDMA(ip_spi)->NDTR=(unsigned int)RemainingSize;
      cIP_SPI_txDMA(ip_spi)->M0AR=(unsigned int)Tx_Buffer;
      cIP_SPI_rxDMA(ip_spi)->NDTR=(unsigned int)RemainingSize;
      cIP_SPI_rxDMA(ip_spi)->M0AR=(unsigned int)Rx_Buffer;

      ip_spi->Mode.Master.RemainingSize=0;
    }

    oIP_DMA_ClearAllBit_IFCR(ip_spi->Instance.DMA_Tx);
    oIP_DMA_ClearAllBit_IFCR(ip_spi->Instance.DMA_Rx);

    cIP_SPI_rxDMA(ip_spi)->CR|=DMA_SxCR_EN;//使能DMA
    cIP_SPI_txDMA(ip_spi)->CR|=DMA_SxCR_EN;//使能DMA
  }
}

//DMA中断调用
static void IP_SPI_MasterFullDuplex_DMA_IRQ(void* v){
  IP_SPI* ip_spi;

  ip_spi=v;

  if(oIP_DMA_GetTC_ISR(ip_spi->Instance.DMA_Rx)!=0U){
    //传输完成

    oIP_DMA_ClearTC_IFCR(ip_spi->Instance.DMA_Rx);//清除标志位

    while((cIP_SPI_txDMA(ip_spi)->CR&DMA_SxCR_EN)!=0U){
    }
    while((cIP_SPI_rxDMA(ip_spi)->CR&DMA_SxCR_EN)!=0U){
    }

    ip_spi->Mode.Master.TransStatusRefresh(ip_spi);

  }
  
}




//状态机刷新
static void IP_SPI_MasterOnlyTx_byte_TransStatusRefresh(void* v){
  IP_SPI* ip_spi;
  int RemainingSize;
  unsigned char* Tx_Buffer;

  ip_spi=v;
  
  RemainingSize=ip_spi->Mode.Master.RemainingSize;
  if(RemainingSize==0){
    //传输完成

    cIP_SPI_txDMA(ip_spi)->CR&=(~DMA_SxCR_TCIE);//失能完成中断
    ip_spi->Mode.Master.Busy=0;//解除忙碌状态
    ip_spi->Mode.Master.CommunicationDoneCallback(ip_spi->Mode.Master.Callback_v);

  }else{
    //传输未完成

    Tx_Buffer=ip_spi->Mode.Master.Tx_Buffer;

    if(RemainingSize>65535){
      cIP_SPI_txDMA(ip_spi)->NDTR=65535U;
      cIP_SPI_txDMA(ip_spi)->M0AR=(unsigned int)Tx_Buffer;

      ip_spi->Mode.Master.RemainingSize=RemainingSize-65535;
      ip_spi->Mode.Master.Tx_Buffer=&Tx_Buffer[65535];
    }else{
      cIP_SPI_txDMA(ip_spi)->NDTR=(unsigned int)RemainingSize;
      cIP_SPI_txDMA(ip_spi)->M0AR=(unsigned int)Tx_Buffer;

      ip_spi->Mode.Master.RemainingSize=0;
    }

    oIP_DMA_ClearAllBit_IFCR(ip_spi->Instance.DMA_Tx);

    cIP_SPI_txDMA(ip_spi)->CR|=DMA_SxCR_EN;//使能DMA
  }
}

//状态机刷新
static void IP_SPI_MasterOnlyTx_uint16_TransStatusRefresh(void* v){
  IP_SPI* ip_spi;
  int RemainingSize;
  unsigned char* Tx_Buffer;

  ip_spi=v;
  
  RemainingSize=ip_spi->Mode.Master.RemainingSize;
  if(RemainingSize==0){
    //传输完成

    cIP_SPI_txDMA(ip_spi)->CR&=(~DMA_SxCR_TCIE);//失能完成中断
    ip_spi->Mode.Master.Busy=0;//解除忙碌状态
    ip_spi->Mode.Master.CommunicationDoneCallback(ip_spi->Mode.Master.Callback_v);

  }else{
    //传输未完成

    Tx_Buffer=ip_spi->Mode.Master.Tx_Buffer;

    if(RemainingSize>65535){
      cIP_SPI_txDMA(ip_spi)->NDTR=65535U;
      cIP_SPI_txDMA(ip_spi)->M0AR=(unsigned int)Tx_Buffer;

      ip_spi->Mode.Master.RemainingSize=RemainingSize-65535;
      ip_spi->Mode.Master.Tx_Buffer=&Tx_Buffer[65535];
    }else{
      cIP_SPI_txDMA(ip_spi)->NDTR=(unsigned int)RemainingSize;
      cIP_SPI_txDMA(ip_spi)->M0AR=(unsigned int)Tx_Buffer;

      ip_spi->Mode.Master.RemainingSize=0;
    }

    oIP_DMA_ClearAllBit_IFCR(ip_spi->Instance.DMA_Tx);

    cIP_SPI_txDMA(ip_spi)->CR|=DMA_SxCR_EN;//使能DMA
  }
}

//DMA中断调用
static void IP_SPI_MasterOnlyTx_DMA_IRQ(void* v){
  IP_SPI* ip_spi;

  ip_spi=v;

  if(oIP_DMA_GetTC_ISR(ip_spi->Instance.DMA_Tx)!=0U){
    //传输完成

    oIP_DMA_ClearTC_IFCR(ip_spi->Instance.DMA_Tx);//清除标志位

    while((cIP_SPI_txDMA(ip_spi)->CR&DMA_SxCR_EN)!=0U){
    }

    ip_spi->Mode.Master.TransStatusRefresh(ip_spi);

  }
  
}



